package com.yuandian.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.yuandian.enums.BaseTableName;
import com.yuandian.enums.TableType;
import com.yuandian.po.FullTableInfo;
import com.yuandian.po.MultipleTableInfo;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 说明：动态表名工具类
 * @Author yanjun
 * @Date 2022/2/21 9:15
 */
public final class DynamicTableNameUtil {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

	private DynamicTableNameUtil() {}

    /**
     * 重载方法，获取动态表名，主要用于查询数据表格
     * @param baseTableName 基础表名枚举，待补全
     * @param startTime 查询的开始时间
     * @param endTime 查询的结束时间
     * @return 结果集
     */
    public static List<FullTableInfo> genFullTableInfo(
			BaseTableName baseTableName,
            String startTime,
            String endTime) {
        return genFullTableInfo(
				baseTableName,
                null,
                startTime,
                endTime,
                null,
                false);
    }

    /**
     * 重载方法，获取动态表名，主要用于查询数据表格
     * @param baseTableName 基础表名枚举，待补全
     * @param formatterSecondTableName 待格式化的秒表。如果秒表与基础表格式不同，则使用该参数
     * @param startTime 查询的开始时间
     * @param endTime 查询的结束时间
     * @return 结果集
     */
    public static List<FullTableInfo> genFullTableInfo(
			BaseTableName baseTableName,
            String formatterSecondTableName,
            String startTime,
            String endTime) {
        return genFullTableInfo(
				baseTableName,
                formatterSecondTableName,
                startTime,
                endTime,
                null,
                false);
    }

    /**
     * 重载方法，获取动态表名，主要用于查询数据表格
     * @param baseTableName 基础表名枚举，待补全
     * @param startTime 查询的开始时间
     * @param endTime 查询的结束时间
     * @param extraParamsMap 额外参数映射
     * @return 结果集
     */
    public static List<FullTableInfo> genFullTableInfo(
			BaseTableName baseTableName,
            String startTime,
            String endTime,
            Map<TableType, Map<String, Object>> extraParamsMap) {
        return genFullTableInfo(
				baseTableName,
                null,
                startTime,
                endTime,
                extraParamsMap,
                false);
    }

    /**
     * 获取动态表名，主要用于查询数据表格
     * @param baseTableName 基础表名枚举，待补全
     * @param formatterSecondTableName 待格式化的秒表。如果秒表与基础表格式不同，则使用该参数
     * @param startTime 查询的开始时间
     * @param endTime 查询的结束时间
     * @param extraParamsMap 额外参数映射
     * @param isDayTableDate 天表是否按天分表
     * @return 结果集
     */
    public static List<FullTableInfo> genFullTableInfo(
			BaseTableName baseTableName,
            String formatterSecondTableName,
            String startTime,
            String endTime,
            Map<TableType, Map<String, Object>> extraParamsMap,
            boolean isDayTableDate) {
		String formatterBaseTableName = baseTableName.getName() + "_%s_%s";
        // 获取当天的开始结束时间
        LocalDate localDateToday = LocalDate.now();
        LocalDateTime localDateTodayStartTime = localDateToday.atTime(0, 0, 0);
        LocalDateTime localDateTodayEndTime = getWholeDay(localDateTodayStartTime, 1);
        long localDateTodayStartTimeUsec = localDateTodayStartTime.toEpochSecond(ZoneOffset.of("+8"));
        long localDateTodayEndTimeUsec = localDateTodayEndTime.toEpochSecond(ZoneOffset.of("+8"));

        LocalDateTime localDateStartTime = LocalDateTime.parse(startTime, DATE_TIME_FORMATTER);
        LocalDateTime localDateEndTime = LocalDateTime.parse(endTime, DATE_TIME_FORMATTER);

        // 开始结束时间间隔
        Duration localDateDuration = Duration.between(getWholeDay(localDateStartTime, 0), getWholeDay(localDateEndTime, 0));
        long dayPeriodSpan = localDateDuration.toDays();

        List<FullTableInfo> mtiList = new ArrayList<>();
        if (dayPeriodSpan > 0) {
            // 跨天，拆成不跨天
            LocalDateTime localDateTempTime = localDateStartTime;
            for (int i = 0; i < dayPeriodSpan; i++) {
                // 获取游标时间的下1个整天
                LocalDateTime nextWholeDay = getWholeDay(localDateTempTime, 1);
                calcuNoAcrossDay(localDateTempTime, nextWholeDay, mtiList);
                localDateTempTime = nextWholeDay;
            }
            long localDateTempTimeUsec = localDateTempTime.toEpochSecond(ZoneOffset.of("+8"));
            long localDateEndTimeUsec = localDateEndTime.toEpochSecond(ZoneOffset.of("+8"));
            if (localDateTempTimeUsec < localDateEndTimeUsec) {
                if (localDateTempTimeUsec >= localDateTodayStartTimeUsec
                        && localDateEndTimeUsec <= localDateTodayEndTimeUsec) {
                    // 在今天之内，一律查分钟表
                    mtiList.add(new FullTableInfo(TableType.MINUTE, localDateTempTime, localDateEndTime));
                } else {
                    calcuNoAcrossDay(localDateTempTime, localDateEndTime, mtiList);
                }
            }
        } else {
            // 不跨天
            long localDateStartTimeUsec = localDateStartTime.toEpochSecond(ZoneOffset.of("+8"));
            long localDateEndTimeUsec = localDateEndTime.toEpochSecond(ZoneOffset.of("+8"));
            if (localDateStartTimeUsec >= localDateTodayStartTimeUsec
                    && localDateEndTimeUsec <= localDateTodayEndTimeUsec) {
                // 在今天之内，一律查分钟表
                mtiList.add(new FullTableInfo(TableType.MINUTE, localDateStartTime, localDateEndTime));
            } else {
                calcuNoAcrossDay(localDateStartTime, localDateEndTime, mtiList);
            }
        }

        // 设置要查询的真实表名
        for (FullTableInfo info : mtiList) {
            Duration between = Duration.between(info.getLocalDateStartTime(), info.getLocalDateEndTime());
            long betweenSecond = between.getSeconds();
            info.setStartTime(DATE_TIME_FORMATTER.format(info.getLocalDateStartTime()));
            info.setEndTime(DATE_TIME_FORMATTER.format(info.getLocalDateEndTime()));
            info.setStartTimeUsec(info.getLocalDateStartTime().toEpochSecond(ZoneOffset.of("+8")));
            info.setEndTimeUsec(info.getLocalDateEndTime().toEpochSecond(ZoneOffset.of("+8")));
            info.setTimeSpan(betweenSecond);
            if (info.getTableType() != null) {
                switch (info.getTableType()) {
                    case DAY:
                        info.setTableName(String.format(
                                formatterBaseTableName, "d", YDateUtil.yyyyMMdd(info.getStartTime())));
                        break;
                    case HOUR:
                        info.setTableName(String.format(
                                formatterBaseTableName, "h", YDateUtil.yyyyMMdd(info.getStartTime())));
                        break;
                    case MINUTE:
                        info.setTableName(String.format(
                                formatterBaseTableName, "m", YDateUtil.yyyyMMdd(info.getStartTime())));
                        break;
                    case SECOND:
                        if (StrUtil.isNotEmpty(formatterSecondTableName)) {
                            info.setTableName(String.format(
                                    formatterSecondTableName, "", YDateUtil.yyyyMMdd(info.getStartTime())));
                        } else {
                            info.setTableName(String.format(
                                    formatterBaseTableName, "s", YDateUtil.yyyyMMdd(info.getStartTime())));
                        }
                        break;
                    default:
                        break;
                }
            } else if (betweenSecond < 60) {
                info.setTableType(TableType.SECOND);
                if (StrUtil.isNotEmpty(formatterSecondTableName)) {
                    info.setTableName(String.format(
                            formatterSecondTableName, "", YDateUtil.yyyyMMdd(info.getStartTime())));
                } else {
                    info.setTableName(String.format(
                            formatterBaseTableName, "s", YDateUtil.yyyyMMdd(info.getStartTime())));
                }
            } else if (betweenSecond < 3600) {
                info.setTableType(TableType.MINUTE);
                info.setTableName(String.format(
                        formatterBaseTableName, "m", YDateUtil.yyyyMMdd(info.getStartTime())));
            } else if (betweenSecond < 86400) {
                info.setTableType(TableType.HOUR);
                info.setTableName(String.format(
                        formatterBaseTableName, "h", YDateUtil.yyyyMMdd(info.getStartTime())));
            } else {
                info.setTableType(TableType.DAY);
                info.setTableName(String.format(formatterBaseTableName, "d", YDateUtil.yyyyMMdd(info.getStartTime())));
            }
            if (CollUtil.isNotEmpty(extraParamsMap) && extraParamsMap.containsKey(info.getTableType())) {
                info.setExtraParams(extraParamsMap.get(info.getTableType()));
            }
        }

        // 天表按天分表
        if (isDayTableDate) {
            return mtiList;
        }

        // 天表不按天分表
        FullTableInfo dayInfo = null;
        List<FullTableInfo> result = new ArrayList<>();
        for (FullTableInfo info : mtiList) {
            if (info.getTableType().equals(TableType.DAY)) {
                if (dayInfo == null) {
                    dayInfo = info;
                    dayInfo.setTableName(dayInfo.getTableName().substring(0, dayInfo.getTableName().lastIndexOf("_")));
                    result.add(dayInfo);
                } else {
                    dayInfo.setEndTime(info.getEndTime());
                    dayInfo.setEndTimeUsec(info.getEndTimeUsec());
                    dayInfo.setLocalDateEndTime(info.getLocalDateEndTime());
                    dayInfo.setTimeSpan(dayInfo.getEndTimeUsec() - dayInfo.getStartTimeUsec());
                    dayInfo.setTableType(TableType.DAY);
                }
            } else {
                result.add(info);
            }
        }
        return result;
    }

    private static void calcuNoAcrossDay(
            LocalDateTime localDateStartTime,
            LocalDateTime localDateEndTime,
            List<FullTableInfo> mtiList) {
        // 开始时间时分秒
        int startTimeMinute = localDateStartTime.getMinute();
        int startTimeSecond = localDateStartTime.getSecond();
        // 结束时间时分秒
        int endTimeHour = localDateEndTime.getHour();
        int endTimeMinute = localDateEndTime.getMinute();
        int endTimeSecond = localDateEndTime.getSecond();
        // 时间差
        Duration duration = Duration.between(localDateStartTime, localDateEndTime);
        long secondSpan = duration.getSeconds();

        // 特殊情况
        if (secondSpan < 60) {
            // 在同一分钟之内
            mtiList.add(new FullTableInfo(TableType.SECOND, localDateStartTime, localDateEndTime));
            return;
        } else if (secondSpan == 60) {
            // 刚好相差一分钟
            if (startTimeSecond == 0) {
                // 并且是整分
                mtiList.add(new FullTableInfo(TableType.MINUTE, localDateStartTime, localDateEndTime));
            } else {
                // 不是整分
                mtiList.add(new FullTableInfo(TableType.SECOND, localDateStartTime, localDateEndTime));
            }
            return;
        } else if (secondSpan < 120 && (endTimeMinute - startTimeMinute) <= 1) {
            // 两分钟之内且分钟相邻
            mtiList.add(new FullTableInfo(TableType.SECOND, localDateStartTime, localDateEndTime));
            return;
        }

        LocalDateTime nextLocalDateTime;
        if (startTimeSecond != 0) {
            // 开始时间不是整分
            // 获取开始时间的下一个整分
            nextLocalDateTime = getWholeMinute(localDateStartTime, 1);
            mtiList.add(new FullTableInfo(localDateStartTime, nextLocalDateTime));
        } else {
            // 开始时间是整分
            nextLocalDateTime = localDateStartTime;
        }

        // 特殊情况
        duration = Duration.between(nextLocalDateTime, localDateEndTime);
        secondSpan = duration.getSeconds();
        if (secondSpan < 3600) {
            // 在同一小时之内
            if (endTimeSecond != 0) {
                // 结束时间不是整分
                // 获取结束时间整分
                LocalDateTime wholeMinute = getWholeMinute(localDateEndTime, 0);
                mtiList.add(new FullTableInfo(TableType.MINUTE, nextLocalDateTime, wholeMinute));
                mtiList.add(new FullTableInfo(TableType.SECOND, wholeMinute, localDateEndTime));
            } else {
                // 结束时间是整分
                mtiList.add(new FullTableInfo(TableType.MINUTE, nextLocalDateTime, localDateEndTime));
            }
            return;
        } else if (secondSpan == 3600) {
            // 刚好相差一小时
            if (nextLocalDateTime.getMinute() == 0) {
                // 并且是整时
                mtiList.add(new FullTableInfo(TableType.HOUR, nextLocalDateTime, localDateEndTime));
            } else {
                // 不是整时
                mtiList.add(new FullTableInfo(TableType.MINUTE, nextLocalDateTime, localDateEndTime));
            }
            return;
        } else if (secondSpan < 7200 && (endTimeHour - nextLocalDateTime.getHour() <= 1)) {
            // 两小时之内且小时相邻
            if (endTimeSecond != 0) {
                // 结束时间不是整分
                // 获取结束时间整分
                LocalDateTime wholeMinute = getWholeMinute(localDateEndTime, 0);
                mtiList.add(new FullTableInfo(TableType.MINUTE, nextLocalDateTime, wholeMinute));
                mtiList.add(new FullTableInfo(TableType.SECOND, wholeMinute, localDateEndTime));
            } else {
                // 结束时间是整分
                mtiList.add(new FullTableInfo(TableType.MINUTE, nextLocalDateTime, localDateEndTime));
            }
            return;
        }

        if (startTimeMinute != 0 || startTimeSecond != 0) {
            // 开始时间不是整时或者不是整分
            // 获取开始时间的下一个整时
            LocalDateTime nextWholeHour = getWholeHour(localDateStartTime, 1);
            mtiList.add(new FullTableInfo(nextLocalDateTime, nextWholeHour));
            nextLocalDateTime = nextWholeHour;
        }

        if (endTimeMinute != 0) {
            // 结束时间不是整时
            // 获取结束时间的整时
            LocalDateTime wholeHour = getWholeHour(localDateEndTime, 0);
            mtiList.add(new FullTableInfo(nextLocalDateTime, wholeHour));
            nextLocalDateTime = wholeHour;
        }

        if (endTimeSecond != 0) {
            // 结束时间如果不是整分
            // 获取结束时间的整分
            LocalDateTime wholeMinute = getWholeMinute(localDateEndTime, 0);
            mtiList.add(new FullTableInfo(nextLocalDateTime, wholeMinute));
            mtiList.add(new FullTableInfo(wholeMinute, localDateEndTime));
        } else {
            mtiList.add(new FullTableInfo(nextLocalDateTime, localDateEndTime));
        }
    }

    /**
     * 获取localDateTime的n个整分
     * @param localDateTime localDateTime
     * @param n n
     * @return 结果
     */
    private static LocalDateTime getWholeMinute(LocalDateTime localDateTime, int n) {
        LocalDateTime wholeLocalDateTime = localDateTime.plusMinutes(n);
        return wholeLocalDateTime
                .toLocalDate()
                .atTime(wholeLocalDateTime.getHour(), wholeLocalDateTime.getMinute(), 0);
    }

    /**
     * 获取localDateTime的n个整时
     * @param localDateTime localDateTime
     * @param n n
     * @return 结果
     */
    private static LocalDateTime getWholeHour(LocalDateTime localDateTime, int n) {
        LocalDateTime wholeLocalDateTime = localDateTime.plusHours(n);
        return wholeLocalDateTime
                .toLocalDate()
                .atTime(wholeLocalDateTime.getHour(), 0, 0);
    }

    /**
     * 获取localDateTime的n个整天
     * @param localDateTime localDateTime
     * @param n n
     * @return 结果
     */
    private static LocalDateTime getWholeDay(LocalDateTime localDateTime, int n) {
        LocalDateTime wholeLocalDateTime = localDateTime.plusDays(n);
        return wholeLocalDateTime
                .toLocalDate()
                .atTime(0, 0, 0);
    }

    /**
     * 根据时间范围补全日期分表
     * @param tableNameNoDate 要补全的表名
     * @param localDateStartTime 开始时间
     * @param localDateEndTime 结束时间
     * @return 表名集
     */
    private static List<String> getTableNamesFromTimeRange(
            String tableNameNoDate, LocalDateTime localDateStartTime, LocalDateTime localDateEndTime) {
        List<String> list = new ArrayList<>();
        Duration localDateDuration = Duration.between(getWholeDay(localDateStartTime, 0), getWholeDay(localDateEndTime, 0));
        long dayPeriodSpan = localDateDuration.toDays();
        LocalDateTime localDateTempTime = localDateStartTime;
        for (int i = 0; i <= dayPeriodSpan; i++) {
            list.add(String.format(tableNameNoDate, DATE_FORMATTER.format(localDateTempTime)));
            localDateTempTime = localDateTempTime.plusDays(1);
        }
        if (localDateEndTime.getHour() == 0 && localDateEndTime.getMinute() == 0 && localDateEndTime.getSecond() == 0) {
            // 结束日期为整天，且表名集大于1，则去掉最后一个表
            if (list.size() > 1) {
                list.remove(list.size() - 1);
            }
        }
        return list;
    }

    /**
     * 一般用于按日期分表，区分分钟表、小时表、天表，但只会返回其中一种类型的表，所以要限制查询时间的选择，趋势图用
     * @param formatterBaseTableName 待格式化的基础表
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 种类表信息
     */
    public static FullTableInfo generalSingleTableNamesFromTimeRange(
            String formatterBaseTableName,
            String startTime,
            String endTime) {
        FullTableInfo info = new FullTableInfo();

        LocalDateTime localDateStartTime = LocalDateTime.parse(startTime, DATE_TIME_FORMATTER);
        LocalDateTime localDateEndTime = LocalDateTime.parse(endTime, DATE_TIME_FORMATTER);

        // 开始结束时间差
        Duration duration = Duration.between(localDateStartTime, localDateEndTime);
        long timeSpan = duration.getSeconds();

        if (timeSpan <= 172800L) {
            // 选择的时间范围小于等于48小时，查询分钟表，数据行范围[120, 2880]，时间必须是HH:mm:00
            info.setTableType(TableType.MINUTE);
            String tableNameNoDate = String.format(formatterBaseTableName, "m", "%s");
            // 获取开始结束时间的整分
            LocalDateTime wholeMinuteStartTime = getWholeMinute(localDateStartTime, 0);
            LocalDateTime wholeMinuteEndTime = localDateEndTime;
            if (wholeMinuteEndTime.getSecond() != 0) {
                wholeMinuteEndTime = getWholeMinute(localDateEndTime, 1);
            }
            info.setStartTime(DATE_TIME_FORMATTER.format(wholeMinuteStartTime));
            info.setEndTime(DATE_TIME_FORMATTER.format(wholeMinuteEndTime));
            info.setTableNameList(getTableNamesFromTimeRange(tableNameNoDate, wholeMinuteStartTime, wholeMinuteEndTime));
        } else if (timeSpan <= 2592000L) {
            // 选择的时间范围小于等于30天，查询小时表，数据行范围[48, 720]，时间必须是HH:00:00
            info.setTableType(TableType.HOUR);
            String tableNameNoDate = String.format(formatterBaseTableName, "h", "%s");
            // 获取开始结束时间的整时
            LocalDateTime wholeHourStartTime = getWholeHour(localDateStartTime, 0);
            LocalDateTime wholeHourEndTime = localDateEndTime;
            if (wholeHourEndTime.getSecond() != 0 || wholeHourEndTime.getMinute() != 0) {
                wholeHourEndTime = getWholeHour(localDateEndTime, 1);
            }
            info.setStartTime(DATE_TIME_FORMATTER.format(wholeHourStartTime));
            info.setEndTime(DATE_TIME_FORMATTER.format(wholeHourEndTime));
            info.setTableNameList(getTableNamesFromTimeRange(tableNameNoDate, wholeHourStartTime, wholeHourEndTime));
        } else {
            // 选择的时间范围大于30天，查询天表，数据行范围[30, +∞)，时间必须是00:00:00
            info.setTableType(TableType.DAY);
            String tableNameNoDate = String.format(formatterBaseTableName, "d", "");
            List<String> tableNameList = new ArrayList<>();
            tableNameList.add(tableNameNoDate.substring(0, tableNameNoDate.length() - 1));
            info.setTableNameList(tableNameList);
            LocalDateTime wholeDayStartTime = getWholeDay(localDateStartTime, 0);
            LocalDateTime wholeDayEndTime = localDateEndTime;
            if (wholeDayEndTime.getSecond() != 0 || wholeDayEndTime.getMinute() != 0 || wholeDayEndTime.getHour() != 0) {
                wholeDayEndTime = getWholeDay(localDateEndTime, 1);
            }
            info.setStartTime(DATE_TIME_FORMATTER.format(wholeDayStartTime));
            info.setEndTime(DATE_TIME_FORMATTER.format(wholeDayEndTime));
        }
        return info;
    }

    /**
     * 一般用于按日期分表，不区分分钟表、小时表、天表
     * @param formatterBaseTableName 待格式化的基础表
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 表名集
     */
    public static List<String> generalTableNamesFromTimeRange(
            String formatterBaseTableName,
            String startTime,
            String endTime) {
        LocalDateTime localDateStartTime = LocalDateTime.parse(startTime, DATE_TIME_FORMATTER);
        LocalDateTime localDateEndTime = LocalDateTime.parse(endTime, DATE_TIME_FORMATTER);
        return getTableNamesFromTimeRange(formatterBaseTableName, localDateStartTime, localDateEndTime);
    }


	/**
	 * 一般用于按日期分表，区分分钟表、小时表、天表，但只会返回其中一种类型的表，所以要限制查询时间的选择，趋势图用
	 * @param startTime 开始时间
	 * @param endTime 结束时间
	 * @return 种类表信息
	 */
	public static MultipleTableInfo generalSingleTableNamesFromTimeRange(
			String startTime,
			String endTime) {
		MultipleTableInfo info = new MultipleTableInfo();

		LocalDateTime localDateStartTime = LocalDateTime.parse(startTime, DATE_TIME_FORMATTER);
		LocalDateTime localDateEndTime = LocalDateTime.parse(endTime, DATE_TIME_FORMATTER);

		// 开始结束时间差
		Duration duration = Duration.between(localDateStartTime, localDateEndTime);
		long timeSpan = duration.getSeconds();

		if (timeSpan <= 172800L) {
			// 选择的时间范围小于等于48小时，查询分钟表，数据行范围[120, 2880]，时间必须是HH:mm:00
			info.setTableType(TableType.MINUTE);
			// 获取开始结束时间的整分
			LocalDateTime wholeMinuteStartTime = getWholeMinute(localDateStartTime, 0);
			LocalDateTime wholeMinuteEndTime = localDateEndTime;
			if (wholeMinuteEndTime.getSecond() != 0) {
				wholeMinuteEndTime = getWholeMinute(localDateEndTime, 1);
			}
			info.setStartTime(DATE_TIME_FORMATTER.format(wholeMinuteStartTime));
			info.setEndTime(DATE_TIME_FORMATTER.format(wholeMinuteEndTime));

		} else if (timeSpan <= 2592000L) {
			// 选择的时间范围小于等于30天，查询小时表，数据行范围[48, 720]，时间必须是HH:00:00
			info.setTableType(TableType.HOUR);
			// 获取开始结束时间的整时
			LocalDateTime wholeHourStartTime = getWholeHour(localDateStartTime, 0);
			LocalDateTime wholeHourEndTime = localDateEndTime;
			if (wholeHourEndTime.getSecond() != 0 || wholeHourEndTime.getMinute() != 0) {
				wholeHourEndTime = getWholeHour(localDateEndTime, 1);
			}
			info.setStartTime(DATE_TIME_FORMATTER.format(wholeHourStartTime));

		} else {
			// 选择的时间范围大于30天，查询天表，数据行范围[30, +∞)，时间必须是00:00:00
			info.setTableType(TableType.DAY);
			LocalDateTime wholeDayStartTime = getWholeDay(localDateStartTime, 0);
			LocalDateTime wholeDayEndTime = localDateEndTime;
			if (wholeDayEndTime.getSecond() != 0 || wholeDayEndTime.getMinute() != 0 || wholeDayEndTime.getHour() != 0) {
				wholeDayEndTime = getWholeDay(localDateEndTime, 1);
			}
			info.setStartTime(DATE_TIME_FORMATTER.format(wholeDayStartTime));
			info.setEndTime(DATE_TIME_FORMATTER.format(wholeDayEndTime));
		}
		return info;
	}


    /**
     * 根据表类型获取最小刻度
     * @param tableType 表类型
     * @return 最小刻度
     */
    public static Integer getMinScaleByTableType(TableType tableType) {
        switch (tableType) {
            case SECOND:
                return 1;
            case MINUTE:
                return 60;
            case HOUR:
                return 3600;
            case DAY:
                return 86400;
            default:
                return 60;
        }
    }

    /**
     * 通过最小刻度和请求刻度选择刻度
     * @param minScale 最小刻度
     * @param baseScale 请求刻度
     * @return 刻度
     */
    public static Integer getScaleByMinScaleAndParam(Integer minScale, Integer baseScale) {
        if (baseScale != null && baseScale > minScale && baseScale % minScale == 0) {
            return baseScale;
        }
        return minScale;
    }
}
